package com.ly.sms.service;

import com.google.common.util.concurrent.RateLimiter;
import com.ly.sms.model.RspEnum;
import com.ly.sms.model.SmsRequest;
import com.ly.sms.model.SmsResp;
import com.ly.sms.utils.DateTimeUtils;
import com.ly.sms.utils.HttpUtils;
import com.ly.sms.utils.HttpUtils.HttpResult;
import com.ly.sms.utils.JsonUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Service;

/**
 * @Author ly
 * @Date 2022-03-26 17:47
 */
@Service
public class SmsService implements BeanFactoryPostProcessor {

  private String mockServerIp = "mock-sms-server";

  private String mockServerPort = "8080";

  private volatile RateLimiter limiter_1 = RateLimiter.create(10);

  private volatile RateLimiter limiter_2 = RateLimiter.create(10);

  private volatile AtomicInteger state_1 = new AtomicInteger(0);
  private volatile AtomicInteger state_2 = new AtomicInteger(0);

  public static volatile Map<String, Long> limits = new ConcurrentHashMap<>(10240);

  /**
   * 发送短信
   * @param request
   *
   * */
  public SmsResp sendMsg(SmsRequest request) {

    Long lastTimeStamp = limits.get(request.getTels());
    long currentTimeMillis = System.currentTimeMillis();
    if (lastTimeStamp != null && ( currentTimeMillis - lastTimeStamp < 1000)) {
      return new SmsResp(RspEnum.QUICKLY_ERROR.getCode(), RspEnum.QUICKLY_ERROR.getMsg());
    }
    limits.put(request.getTels(), currentTimeMillis);

    if ("1".equals(request.getQos())) {
      // 优先级最高
      if (limiter_1.tryAcquire()) {
        try {
          state_1.getAndIncrement();
          return doSendMsg(request);
        }finally {
          state_1.getAndDecrement();
        }
      }
      return new SmsResp(RspEnum.QUICKLY_ERROR.getCode(), RspEnum.QUICKLY_ERROR.getMsg());
    }

    if ("2".equals(request.getQos())) {
      // 优先级次高
      if (state_1.get() >= 10) {
        return new SmsResp(RspEnum.QUICKLY_ERROR.getCode(), RspEnum.QUICKLY_ERROR.getMsg());
      }

      if (limiter_2.tryAcquire()) {
        try {
          state_2.getAndIncrement();
          return doSendMsg(request);
        }finally {
          state_2.getAndDecrement();
        }
      }
    }

    if ("3".equals(request.getQos())) {
      // 优先级最低
      if (state_1.get() >= 10) {
        return new SmsResp(RspEnum.QUICKLY_ERROR.getCode(), RspEnum.QUICKLY_ERROR.getMsg());
      }

      if (state_2.get() + state_1.get() >= 10) {
        return new SmsResp(RspEnum.QUICKLY_ERROR.getCode(), RspEnum.QUICKLY_ERROR.getMsg());
      }

      return doSendMsg(request);
    }

    return new SmsResp(RspEnum.QUICKLY_ERROR.getCode(), RspEnum.QUICKLY_ERROR.getMsg());
  }

  private SmsResp doSendMsg(SmsRequest request) {
    Map<String, Object> map1 = new HashMap<>();
    map1.put("qos", request.getQos());
    map1.put("acceptor_tel", request.getTels());
    map1.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateTimeUtils.ISO_DATE_TIME_PATTERN)));
    Map<String, String> map2 = new HashMap<>();
    map2.put("title", request.getTitle());
    map2.put("content", request.getContent());

    map1.put("template_param", map2);

    Map<String, String> header = new HashMap<>();
    header.put("Content-Type", "application/json");

    try {
      String url = "http://" + mockServerIp + ":" +  mockServerPort + "/v2/emp/templateSms/sendSms";
      System.out.println("url:" + url);
      HttpResult post = HttpUtils.getInstance().post(url, Charset.defaultCharset(), JsonUtils.toJson(map1), header, 5000);
      System.out.println("result:" + post.getContent());

      if (post.getStatusCode() == 200 && post.getContent() != null) {

        SmsRsp smsRsp = JsonUtils.fromJson(post.getContent(), SmsRsp.class);


        if (StringUtils.equals("0", smsRsp.getRes_code())) {
          return new SmsResp(RspEnum.SUCCESS.getCode(), RspEnum.SUCCESS.getMsg());
        }
        return new SmsResp(RspEnum.SEND_MSG_ERROR.getCode(), RspEnum.SEND_MSG_ERROR.getMsg() + ":" + smsRsp.getRes_message());
      }

    } catch (URISyntaxException e) {
      // 测试环境不写 logger了
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

    return new SmsResp(RspEnum.SEND_MSG_ERROR.getCode(), RspEnum.SEND_MSG_ERROR.getMsg());
  }

  @Override
  public void postProcessBeanFactory(
      ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    // 初始化一下ip 端口
//    mockServerIp = System.getenv("${MOKE_SERVER_HOST}");
//    mockServerPort = System.getenv("${MOKE_SERVER_PORT}");
//
//    System.out.println( "" + mockServerIp);
//    System.out.println(mockServerPort);
  }
}
